/*
 * Copyright (c) 2018-2999 湖南洛云网络科技有限公司 All rights reserved.
 *
 * https://www.gz-yami.com/
 *
 */

package com.yami.shop.seckill.comment.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yami.shop.bean.enums.OfflineHandleEventStatus;
import com.yami.shop.bean.enums.OfflineHandleEventType;
import com.yami.shop.bean.enums.ProdType;
import com.yami.shop.bean.event.RemoveDiscountProdByIdsEvent;
import com.yami.shop.bean.model.OfflineHandleEvent;
import com.yami.shop.bean.model.Product;
import com.yami.shop.bean.param.OfflineHandleEventAuditParam;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.dao.ProductMapper;
import com.yami.shop.seckill.comment.enums.SeckillEnum;
import com.yami.shop.seckill.comment.dto.SeckillProductSimpleDto;
import com.yami.shop.seckill.comment.model.Seckill;
import com.yami.shop.seckill.comment.dao.SeckillMapper;
import com.yami.shop.seckill.comment.model.SeckillSku;
import com.yami.shop.seckill.comment.service.SeckillService;
import com.yami.shop.seckill.comment.service.SeckillSkuService;
import com.yami.shop.service.OfflineHandleEventService;
import lombok.AllArgsConstructor;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 秒杀信息
 *
 * @author LGH
 * @date 2019-08-28 09:36:59
 */
@Service
@AllArgsConstructor
public class SeckillServiceImpl extends ServiceImpl<SeckillMapper, Seckill> implements SeckillService {

    private final SeckillMapper seckillMapper;

    private final SeckillSkuService seckillSkuService;

    private final ProductMapper productMapper;

    private final OfflineHandleEventService offlineHandleEventService;
    private final ApplicationContext applicationContext;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveSeckill(Seckill seckill, List<SeckillSku> seckillSkus) {


        seckill.setStatus(1);
        seckill.setIsDelete(0);
        // 保存秒杀信息
        seckillMapper.insert(seckill);
        seckillSkus.forEach(seckillSku -> seckillSku.setSeckillId(seckill.getSeckillId()));

        // 保存秒杀sku信息
        seckillSkuService.saveBatch(seckillSkus);

        // 更新商品信息
        Product product = new Product();
        product.setActivityId(seckill.getSeckillId());
        product.setProdType(ProdType.PROD_TYPE_SECKILL.value());
        product.setProdId(seckill.getProdId());
        productMapper.updateById(product);
        // 发送事件，清除掉如果是限时特惠中的可用商品
        applicationContext.publishEvent(new RemoveDiscountProdByIdsEvent(Collections.singletonList(seckill.getProdId())));
    }

    /**
     * 这里的缓存时间参考RedisCacheConfig#getRedisCacheConfigurationMap
     * @param seckillId
     * @return
     */
    @Override
    @Cacheable(cacheNames = "SeckillById", key = "#seckillId")
    public Seckill getSeckillById(Long seckillId) {
        return seckillMapper.selectById(seckillId);
    }

    @Override
    @CacheEvict(cacheNames = "SeckillById", key = "#seckillId")
    public void removeSeckillCacheById(Long seckillId) {
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void invalidById(Seckill seckill) {

        Product productParam = new Product();
        productParam.setProdId(seckill.getProdId());
        productParam.setActivityId(0L);
        productParam.setProdType(ProdType.PROD_TYPE_NORMAL.value());
        productMapper.updateById(productParam);

        seckill.setStatus(0);
        seckillMapper.updateById(seckill);
    }

    @Override
    public IPage<SeckillProductSimpleDto> pageSeckillProd(PageParam<SeckillProductSimpleDto> page, Integer dbLang) {
        return seckillMapper.pageSeckillProd(page,dbLang);
    }

    @Override
    public IPage<Seckill> getPlatformSeckillPage(PageParam<Seckill> page, Seckill seckill) {
        return seckillMapper.getPlatformSeckillPage(page, seckill);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void offline(Seckill seckill, String offlineReason, Long sysUserId) {

        // 添加下线处理记录
        Date now = new Date();
        OfflineHandleEvent offlineHandleEvent = new OfflineHandleEvent();
        offlineHandleEvent.setHandleId(seckill.getSeckillId());
        offlineHandleEvent.setCreateTime(now);
        offlineHandleEvent.setHandleType(OfflineHandleEventType.SECKILL.getValue());
        offlineHandleEvent.setHandlerId(sysUserId);
        offlineHandleEvent.setShopId(seckill.getShopId());
        offlineHandleEvent.setOfflineReason(offlineReason);
        offlineHandleEvent.setStatus(OfflineHandleEventStatus.OFFLINE_BY_PLATFORM.getValue());
        offlineHandleEvent.setUpdateTime(now);
        offlineHandleEventService.save(offlineHandleEvent);

        // 更新活动状态为下线
        seckillMapper.updateStatus(seckill.getSeckillId(), SeckillEnum.OFFLINE.getValue());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void auditSeckill(OfflineHandleEventAuditParam offlineHandleEventAuditParam, Long sysUserId) {
        // 审核通过
        if (Objects.equals(offlineHandleEventAuditParam.getStatus(), OfflineHandleEventStatus.AGREE_BY_PLATFORM.getValue())) {
            // 更新秒杀活动为正常状态
            seckillMapper.updateStatus(offlineHandleEventAuditParam.getHandleId(), SeckillEnum.NORMAL.getValue());
        }
        // 审核不通过
        else if (Objects.equals(offlineHandleEventAuditParam.getStatus(), OfflineHandleEventStatus.DISAGREE_BY_PLATFORM.getValue())) {
            seckillMapper.updateStatus(offlineHandleEventAuditParam.getHandleId(), SeckillEnum.OFFLINE.getValue());
        }
        // 更新审核时间
        offlineHandleEventService.auditOfflineEvent(offlineHandleEventAuditParam, sysUserId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void auditApply(Long eventId, Long seckillId, String reapplyReason) {
        // 更新活动为待审核状态
        seckillMapper.updateStatus(seckillId, SeckillEnum.WAIT_AUDIT.getValue());

        // 更新事件状态
        offlineHandleEventService.updateToApply(eventId, reapplyReason);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeProdTypeBySeckillIdList(List<Long> seckillIds) {
        seckillMapper.changeProdTypeBySeckillIdList(seckillIds);
        seckillMapper.changeSeckillStatusBySeckillIdList(seckillIds);
    }

    @Override
    public Seckill getSeckillByOrderNumber(String orderNumber) {
        return seckillMapper.getSeckillByOrderNumber(orderNumber);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addInventory(Long seckillId, Integer count) {
        seckillMapper.addInventory(seckillId, count);
    }

}
